package com.wsc.crawler.init;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.http.HttpHost;

import com.wsc.Config;

public class CrawlerConfig implements Config {

	private String User_Agent;
	private int Politeness_Delay;
	private int Request_Timeout;
	private int Frontier_Size;
	private int Crawler_Threads;
	private String Tmp_dir;
	private String	xml_file;
	private String Log_dir;
	private int max_crawler_threads=100;
	private List<String> Include_Domains;
	private List<String> Exclude_Domains;
	private List<String> Exclude_Hosts;
	private List<String> Allowed_MIME_Types;
	private List<String> Allowed_Schemes;
	private boolean Ignore_Robots;
	private String Seed_Urls_From;
	private HttpHost HeartBeat_Host;
	
	
	
	public HttpHost getHeartBeat_Host() {
		
		String host = (String) config
				.getProperty("/property/entry[@name='HeartBeat_Server']");

		HierarchicalConfiguration node = config
				.configurationAt("/property/entry[@name='HeartBeat_Server']");
		int port = Integer.parseInt(node.getString("@port"));

		 HeartBeat_Host = new HttpHost(host, port);
		
		return  HeartBeat_Host;
	}

	
	
	public void setHeartBeat_Host(HttpHost heartBeat_Host) {
		HeartBeat_Host = heartBeat_Host;
	}

	public int getMax_crawler_threads() {
		max_crawler_threads = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='max_crawler_threads']"));
		return max_crawler_threads;
	}

	public void setMax_crawler_threads(int max_grabber_threads) {
		this.max_crawler_threads = max_grabber_threads;
	}

	private List<String> Extract_Links_From;
	private long dept;
	private int Heartbeat_Delay;
	private int Snapshot_Delay;
	private String Wsdl_Filter_Expression;
	private int Retry_Atempts;
	private HttpHost frontierHost = null;
	private HttpHost indexerHost = null;
	// default is 5.
	private int retry_attempts_to_server = 5;

	
	public int getRetry_attempts_to_server() {
		retry_attempts_to_server = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='retry_attempts_to_server']"));
		return retry_attempts_to_server;
	}

	public void setRetry_attempts_to_server(int retry_attempts_to_server) {
		this.retry_attempts_to_server = retry_attempts_to_server;
	}

	public HttpHost getFrontierHost() throws UnknownHostException {
		String host = (String) config
				.getProperty("/property/entry[@name='urlserver']");

		HierarchicalConfiguration node = config
				.configurationAt("/property/entry[@name='urlserver']");
		int port = Integer.parseInt(node.getString("@port"));

		frontierHost = new HttpHost(host, port);
		return frontierHost;
	}

	public void setFrontierHost(HttpHost frontierhost) {
		frontierHost = frontierhost;
	}

	public HttpHost getIndexerHost() throws UnknownHostException {

		String host = (String) config
				.getProperty("/property/entry[@name='indexserver']");

		HierarchicalConfiguration node = config
				.configurationAt("/property/entry[@name='indexserver']");

		int port = Integer.parseInt(node.getString("@port"));

		 indexerHost = new HttpHost(host, port);
		return indexerHost;
	}

	public void setIndexerHost(HttpHost indexerhost) {
		indexerHost = indexerhost;
	}

	public XMLConfiguration config = null;

	// Constructor

	public CrawlerConfig() {

	}

	public int getRetry_Atempts() {
		Retry_Atempts = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='retry_atempts']"));
		return Retry_Atempts;
	}

	public void setRetry_Atempts(int retry_Atempts) {
		Retry_Atempts = retry_Atempts;
	}

	public int getNumberOfEntries() {
		int num = this.config.getList("property.entry[@name]").size();
		System.out.println(num);
		return num;
	}

	public String getUser_Agent() {
		User_Agent = (String) config
				.getProperty("/property/entry[@name='user-agent']");
		return User_Agent;
	}

	public void setUser_Agent(String user_Agent) {
		User_Agent = user_Agent;
	}

	public int getPoliteness_Delay() {
		Politeness_Delay = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='politeness-delay']"));
		return Politeness_Delay;
	}

	public void setPoliteness_Delay(int politeness_Delay) {
		Politeness_Delay = politeness_Delay;
	}

	public int getRequest_Timeout() {
		Request_Timeout = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='request-timeout']"));
		return Request_Timeout;
	}

	public void setRequest_Timeout(int request_Timeout) {
		Request_Timeout = request_Timeout;
	}

	public int getFrontier_Size() {
		Frontier_Size = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='frontier-size']"));
		return Frontier_Size;
	}

	public void setFrontier_Size(int frontier_Size) {
		Frontier_Size = frontier_Size;
	}

	public int getCrawler_Threads() {
		Crawler_Threads = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='crawler-threads']"));
		return Crawler_Threads;
	}

	public void setCrawler_Threads(int crawler_Threads) {
		Crawler_Threads = crawler_Threads;
	}

	public String getTmp_dir() {
		Tmp_dir = (String) config
				.getProperty("/property/entry[@name='tmp-dir']");
		return Tmp_dir;
	}

	public void setTmp_dir(String tmp_dir) {
		Tmp_dir = tmp_dir;
	}

	public String getXML_Filename(){
		HierarchicalConfiguration node = config
				.configurationAt("/property/entry[@name='tmp-dir']");

		xml_file = node.getString("@file");
		return xml_file;
	}
	public String getLog_dir() {
		Log_dir = (String) config
				.getProperty("/property/entry[@name='log-dir']");
		return Log_dir;
	}

	public void setLog_dir(String log_dir) {
		Log_dir = log_dir;
	}

	public List<String> getInclude_Domains() {
		Include_Domains = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='include-domains']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Include_Domains.add(tokens.nextToken());
			}

		}
		return Include_Domains;
	}

	public void setInclude_Domains(List<String> include_Domains) {
		Include_Domains = include_Domains;
	}

	public List<String> getExclude_Domains() {
		Exclude_Domains = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='exclude-domains']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Exclude_Domains.add(tokens.nextToken());
			}

		}

		return Exclude_Domains;
	}

	public void setExclude_Domains(List<String> exclude_Domains) {
		Exclude_Domains = exclude_Domains;
	}

	public List<String> getExclude_Hosts() {
		Exclude_Hosts = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='exclude_hosts']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Exclude_Hosts.add(tokens.nextToken());
			}

		}
		return Exclude_Hosts;
	}

	public void setExclude_Hosts(List<String> exclude_Hosts) {
		Exclude_Hosts = exclude_Hosts;
	}

	public List<String> getAllowed_MIME_Types() {
		Allowed_MIME_Types = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='allowed_types']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Allowed_MIME_Types.add(tokens.nextToken());
			}

		}
		return Allowed_MIME_Types;
	}

	public void setAllowed_MIME_Types(List<String> allowed_MIME_Types) {
		Allowed_MIME_Types = allowed_MIME_Types;
	}

	public List<String> getAllowed_Schemes() {
		Allowed_Schemes = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='allowed_schemes']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Allowed_Schemes.add(tokens.nextToken());
			}

		}
		return Allowed_Schemes;
	}

	public void setAllowed_Schemes(List<String> allowed_Schemes) {
		Allowed_Schemes = allowed_Schemes;
	}

	public boolean isIgnore_Robots() {
		Ignore_Robots = (Boolean) config
				.getProperty("/property/entry[@name='ignore-robots']");
		return Ignore_Robots;
	}

	public void setIgnore_Robots(boolean ignore_Robots) {
		Ignore_Robots = ignore_Robots;
	}

	public String getSeed_Urls_From() {
		Seed_Urls_From = (String) config
				.getProperty("/property/entry[@name='seed_urls_from']");
		return Seed_Urls_From;
	}

	public void setSeed_Urls_From(String seed_Urls_From) {
		Seed_Urls_From = seed_Urls_From;
	}

	public List<String> getExtract_Links_From() {
		Extract_Links_From = new ArrayList<String>();
		String property = (String) config
				.getProperty("/property/entry[@name='extract-Links-from']");
		StringTokenizer tokens = new StringTokenizer(property, ".");
		if (tokens.countTokens() > 0) {
			while (tokens.hasMoreTokens()) {

				Extract_Links_From.add(tokens.nextToken());
			}

		}
		return Extract_Links_From;
	}

	public void setExtract_Links_From(List<String> extract_Links_From) {
		Extract_Links_From = extract_Links_From;
	}

	public long getDept() {
		dept = Long.parseLong((String) config
				.getProperty("/property/entry[@name='dept']"));
		return dept;
	}

	public void setDept(long dept) {
		this.dept = dept;
	}

	public int getHeartbeat_Delay() {
		Heartbeat_Delay = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='heartbeat_delay']"));
		return Heartbeat_Delay;
	}

	public void setHeartbeat_Delay(int heartbeat_Delay) {
		Heartbeat_Delay = heartbeat_Delay;
	}

	public int getSnapshot_Delay() {
		Snapshot_Delay = Integer.parseInt((String) config
				.getProperty("/property/entry[@name='snapshot-delay']"));
		return Snapshot_Delay;
	}

	public void setSnapshot_Delay(int snapshot_Delay) {
		Snapshot_Delay = snapshot_Delay;
	}

	public String getWsdl_Filter_Expression() {
		Wsdl_Filter_Expression = (String) config
				.getProperty("/property/entry[@name='wsdl_filter_expression']");
		return Wsdl_Filter_Expression;
	}

	public void setWsdl_Filter_Expression(String wsdl_Filter_Expression) {
		Wsdl_Filter_Expression = wsdl_Filter_Expression;
	}

	public XMLConfiguration getConfig() {
		return config;
	}

	// set with aleardy existing config object
	public void setConfig(XMLConfiguration config) {
		this.config = config;
	}

	/**
	 * This method takes File object as input and set it in config object, if
	 * file does not exist, then load default configuration.
	 */

	@Override
	public void loadXmlFile(File file) throws FileNotFoundException {
		File f;
		// check file existence
		if (file != null && file.exists()) {
			f = file;
		} else {
			// default file location
			f = new File("config/crawler-core.xml");
		}
		// System.out.println(f.toString());
		// create new xmlconfig obj
		try {
			config = new XMLConfiguration(f);

			// config.load();
		} catch (ConfigurationException e) {
			e.printStackTrace();
		}
		// set expression engine to exexute xpath queries on config.xml file

		config.setExpressionEngine(new XPathExpressionEngine());
	}

	public void loadDefaultXmlFile() {
		File f = new File("config/crawler-core.xml");
		if (!f.exists()) {
			try {
				throw new FileNotFoundException();
			} catch (FileNotFoundException e) {
				System.out.println("crawler-core.xml file is not found in "
						+ f.getPath() + " Location.");
			}
		} else {
			try {
				config = new XMLConfiguration(f);
			} catch (ConfigurationException e) {
				System.out.println("Configuration exception in "
						+ CrawlerConfig.class.getCanonicalName());
			}
			config.setExpressionEngine(new XPathExpressionEngine());
		}
	}

	/**
	 * Validate while loading XML configuration file.
	 */

	@Override
	public boolean isValidConfig() {
		// set validating true

		config.setValidating(true);
		// try {
		// load with validation

		// } catch (ConfigurationException e) {

		// e.printStackTrace();
		// }
		return false;
	}

}
